<!--
 * @Description  : 新增编辑组件
 * @Author       : XiaoLei
 * @Date         : 2020-09-09 15:27:59
 * @LastEditTime: 2021-08-03 17:50:20
 * @LastEditors: scg
-->

<template>
  <component
    :is="mTag"
    v-model:visible="visible"
    unmount-on-close
    :footer="mTag === 'a-drawer' ? true : false"
    :title="title"
    :width="width"
    v-bind="modalAttr"
    :mask-closable="maskClosable"
  >
    <VForm
      ref="vform"
      v-model:loading="loading"
      v-bind="$attrs"
      :value="value"
      :fields="fields"
      :show-btn="mTag !== 'a-drawer' ? true : false"
      @get-form="setForm"
      @submit="submit"
      @cancel="cancel"
    >
      <template v-for="f in customFields" #[f.slot]="rest">
        <slot :name="f.slot" v-bind="rest" />
      </template>
    </VForm>
    <template v-if="mTag === 'a-drawer'" #footer>
      <div style="text-align: center; width: 100%">
        <AButton :size="btnSize" style="margin-right: 10px" @click="$cancel">
          {{ cancelText || '取消' }}
        </AButton>
        <AButton
          :size="btnSize"
          type="primary"
          :loading="loading"
          @click="$submit"
        >
          {{ okText || '提交' }}
        </AButton>
      </div>
    </template>
  </component>
</template>

<script lang="ts" setup>
  import { ref, computed, defineExpose } from 'vue';
  import { Message } from '@arco-design/web-vue';
  import VForm from '../form/index.vue';

  const props = defineProps({
    mTag: {
      type: String,
      default: 'AModal',
    },
    size: {
      type: String,
      validator: (value: string) =>
        ['mini', 'small', 'medium', 'large'].includes(value),
      default: 'medium' as any,
    },
    cancelText: String,
    okText: String,
    // 编辑时获取原有数据的方法
    httpGet: Function,
    // 获取数据后对数据进行处理的方法
    getHandler: {
      type: Function,
      default: (value: any) => value.data,
    },
    // 新增编辑提交前对数据进行处理的方法
    handler: {
      type: Function,
      default: (value: any) => value,
    },
    // 新增的方法
    httpAdd: Function,
    // 编辑的方法
    httpEdit: Function,
    // modal宽度
    width: {
      type: [String, Number],
      default: '700px',
    },
    // 点击蒙层是否允许关闭
    maskClosable: Boolean,
    // 编辑时的标题
    editTitle: {
      type: String,
      default: '编辑',
    },
    // 新增时的标题
    addTitle: {
      type: String,
      default: '新增',
    },
    // 自定义提交，覆盖原有函数
    customSubmit: Function,
    // 对话框额外参数
    modalAttr: Object,
    // 表单默认值
    defaultValue: Object,
    // 字段数组
    fields: {
      type: Array,
      default: () => [],
    },
    idKey: {
      type: String,
      default: 'id',
    },
  });
  const vform = ref();
  const visible = ref(false);
  const value = ref({});
  const dataId = ref(0);
  const loading = ref(false);
  const form = ref();
  // 定义 emit
  const emit = defineEmits(['open', 'reload', 'cancel']);
  const title = computed(() => {
    return dataId.value ? props.editTitle : props.addTitle;
  });
  const customFields = computed(() => {
    return props.fields.filter((i: any) => i.slot) as any;
  });
  const btnSize = computed(() => {
    const { size } = props;
    return size as any;
  });
  // 获取初始值
  const getItem = () => {
    if (!dataId.value) return;
    if (!props.httpGet) {
      // eslint-disable-next-line no-console
      console.error('[VEditModal]: no httpGet');
      return;
    }
    loading.value = true;
    props.httpGet(dataId.value).then((res: any) => {
      value.value = props.getHandler(res);
      loading.value = false;
    });
  };
  const show = (sid: number, sValue: any) => {
    loading.value = false;
    value.value = { ...props.defaultValue, ...sValue };
    dataId.value = sid;
    getItem();
    emit('open', dataId, value);
    visible.value = true;
  };
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const setvalue = (fValue: { value: any }) => {
    value.value = { ...props.defaultValue, ...fValue };
  };
  const setForm = (fForm: any) => {
    form.value = { ...props.defaultValue, ...fForm };
  };
  const submit = (fValue: any) => {
    if (props.customSubmit) {
      props.customSubmit(dataId, {
        ...value.value,
        ...fValue,
      });
      return;
    }
    const data = props.handler({
      ...value.value,
      ...fValue,
    });
    if (!data) {
      return;
    }
    loading.value = true;
    if (dataId.value) {
      if (!props.httpEdit) {
        // eslint-disable-next-line no-console
        console.error('[VEditModal]: no httpEdit');
        return;
      }
      // dataId.value,

      props
        .httpEdit(data, dataId.value)
        .then(({ code, msg }: { [x: string]: any }) => {
          if (code === 200) {
            emit('reload');
            Message.success(`${props.editTitle}成功`);
            visible.value = false;
          } else {
            Message.error(msg);
          }
          loading.value = false;
        })
        .catch(() => {
          loading.value = false;
        });
    } else {
      if (!props.httpAdd) {
        // eslint-disable-next-line no-console
        console.error('[VEditModal]: no httpAdd');
        return;
      }
      props
        .httpAdd(data, dataId.value)
        .then(({ code, msg }: { [x: string]: any }) => {
          if (code === 200) {
            emit('reload');
            Message.success(`${props.addTitle}成功`);
            visible.value = false;
          } else {
            Message.error(msg);
          }
          loading.value = false;
        })
        .catch(() => {
          loading.value = false;
        });
    }
  };
  const cancel = () => {
    emit('cancel');
    visible.value = false;
  };
  const $cancel = () => {
    vform.value.cancel();
  };
  const $submit = () => {
    vform.value.validate();
  };
  defineExpose({
    cancel,
    show,
    visible,
  });
</script>
